﻿using System;


using Library.OrmEnterpriseEntity.Factor;

namespace Library.OrmEnterpriseEntity.TableInfo {
	/// <summary>
	/// Generic string column
	/// </summary>
	public abstract class StringColumn : Column<String>, IConvertible {
		protected readonly StringColumnView StringMetadata;
		/// <summary>
		/// Default string value
		/// </summary>
		public static readonly String DefaultString = String.Empty;


		internal static readonly Type StringColumnType = typeof(StringColumn);


		protected StringColumn(StringColumnView metadata, DbTable table)
			: base(metadata, table) {
			StringMetadata = metadata;
		}
		public override string ToString(string format, IFormatProvider formatProvider) {
			return Value.ToString(formatProvider);
		}

		protected override string Default {
			get { return DefaultString; }
		}
		/// <summary>
		/// Len is -1, mean use max len
		/// </summary>

		public virtual int Len {
			get { return StringMetadata.Len; }
		}

		public override bool Validate() {
			if (Value.Length > Len && Len != -1) {
				var e = new ThrowValidationExceptionEventArgs(this, ValidationError.ValueExistInDb);
				Table.OnThrowValidation(e);
				var error = e.Message;
				if (String.IsNullOrEmpty(error))
					error = DbContext.Instance.Context.StringResource.ColumnMaxLenReach(this, e.ColumnName, e.ColumnValue, e.TableName);
				throw new ValidattionException(error, this);
			}
			return base.Validate();
		}

		//public override DbType DbType {
		//  get { return DbType.String; }
		//}

		protected override string ConvertFrom(object value) {
			if (value == null) return String.Empty;
			return value.ToString();
		}

		protected override bool Equal(string t1, string t2) {
			return t1 == t2;
		}

		/// <summary>
		/// 
		/// </summary>
		//public virtual bool IsPassword { get { return StringMetadata.IsPassword; } }
		internal override bool ValueNotDefault {
			get { return Value != String.Empty; }
		}

		protected override void SetValue(ref string oldValue, string newValue) {
			if (newValue == null) newValue = String.Empty;
			base.SetValue(ref oldValue, newValue);
		}

		#region Implementation of IConvertible

		TypeCode IConvertible.GetTypeCode() {
			return Value.GetTypeCode();
		}

		bool IConvertible.ToBoolean(IFormatProvider provider) {
			return ((IConvertible)Value).ToBoolean(provider);
		}

		char IConvertible.ToChar(IFormatProvider provider) {
			return ((IConvertible)Value).ToChar(provider);
		}

		sbyte IConvertible.ToSByte(IFormatProvider provider) {
			return ((IConvertible)Value).ToSByte(provider);
		}

		byte IConvertible.ToByte(IFormatProvider provider) {
			return ((IConvertible)Value).ToByte(provider);
		}

		short IConvertible.ToInt16(IFormatProvider provider) {
			return ((IConvertible)Value).ToInt16(provider);
		}

		ushort IConvertible.ToUInt16(IFormatProvider provider) {
			return ((IConvertible)Value).ToUInt16(provider);
		}

		int IConvertible.ToInt32(IFormatProvider provider) {
			return ((IConvertible)Value).ToInt32(provider);
		}

		uint IConvertible.ToUInt32(IFormatProvider provider) {
			return ((IConvertible)Value).ToUInt32(provider);
		}

		long IConvertible.ToInt64(IFormatProvider provider) {
			return ((IConvertible)Value).ToInt64(provider);
		}

		ulong IConvertible.ToUInt64(IFormatProvider provider) {
			return ((IConvertible)Value).ToUInt64(provider);
		}

		float IConvertible.ToSingle(IFormatProvider provider) {
			return ((IConvertible)Value).ToSingle(provider);
		}

		double IConvertible.ToDouble(IFormatProvider provider) {
			return ((IConvertible)Value).ToDouble(provider);
		}

		decimal IConvertible.ToDecimal(IFormatProvider provider) {
			return ((IConvertible)Value).ToDecimal(provider);
		}

		DateTime IConvertible.ToDateTime(IFormatProvider provider) {
			return ((IConvertible)Value).ToDateTime(provider);
		}

		string IConvertible.ToString(IFormatProvider provider) {
			return Value.ToString(provider);
		}

		object IConvertible.ToType(Type conversionType, IFormatProvider provider) {
			return ((IConvertible)Value).ToType(conversionType, provider);
		}

		#endregion


	}
}
